package com.rymcu.subject.controller;

import com.rymcu.subject.entity.Question;
import com.rymcu.subject.entity.SubjectFile;
import com.rymcu.subject.entity.SubjectOption;
import com.rymcu.subject.result.GlobalResult;
import com.rymcu.subject.service.SubjectFileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import static com.rymcu.subject.result.GlobalResultGenerator.genErrorResult;
import static com.rymcu.subject.result.GlobalResultGenerator.genSuccessResult;
import static org.apache.logging.log4j.util.Strings.isNotBlank;

/**
 * 上传文件服务
 *
 * @author 🐛
 * @date Created in 2021/8/3 15:28
 */
@Api("上传文件服务")
@RequestMapping("/file")
@Controller
public class UploadController {
    private static final Logger LOGGER = LoggerFactory.getLogger(UploadController.class);
    private static final String XLS_CONTENT_TYPE = "application/vnd.ms-excel";
    private static final String XLSX_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    private static final String OPTION_RANGE = "ABCDEFG";


    @Value("${app.upload-path:}")
    private String uploadPth;

    @Autowired
    private SubjectFileService subjectFileService;

    /**
     * @param file
     *         题库文件
     * @param createdBy
     *         提交人id
     * @return
     * @throws IOException
     */
    @ApiOperation("向题库插入文件")
    @PostMapping("/upload")
    @ResponseBody
    public GlobalResult upload(
            @RequestParam("file") MultipartFile file,
            long createdBy
    )
            throws IOException {


        if (file.isEmpty()) {
            return genErrorResult("文件不能为空");
        }
        final String fileContentType = file.getContentType();


        if (!XLS_CONTENT_TYPE.equals(fileContentType) && !XLSX_CONTENT_TYPE.equals(fileContentType)) {
            return genErrorResult("文件类型不匹配");
        }

        final List<Question> questionList = new LinkedList<>();
        loadQuestionFromFile(questionList, file);
        if (questionList.size() < 5L) {
            return genErrorResult("文件内题目不得少于5条");
        }

        final String fileName = file.getOriginalFilename();
        final String uuid = UUID.randomUUID().toString();
        final long fileSize = file.getSize();
        final Date now = new Date();
        final SubjectFile subjectFile = new SubjectFile(0L, uuid, createdBy, now, fileName, fileSize);
        subjectFileService.insert(subjectFile);
        final long sfId = subjectFile.getId();
        subjectFileService.insertSubjects(questionList, sfId, createdBy, now);
        File dest = new File(uploadPth + fileName);
        try {
            file.transferTo(dest);
            LOGGER.info("上传成功");
            return genSuccessResult("上传成功");
        } catch (IOException e) {
            LOGGER.error(e.toString(), e);
        }

        return genErrorResult("上传失败");
    }


    /**
     * 从文件加载题
     *
     * @param questionList
     * @param file
     * @throws IOException
     */
    private static void loadQuestionFromFile(
            List<Question> questionList,
            MultipartFile file
    )
            throws IOException {
        try (final InputStream fileStream = file.getInputStream()) {
            final Workbook workbook = WorkbookFactory.create(fileStream);
            final int sheetNumber = workbook.getNumberOfSheets();
            int sheetIndex = 0;
            int currentIndex = -1;
            boolean currentFlag = true;
            int currentOptionIndex = -1;
            while (sheetIndex < sheetNumber) {
                final Sheet sheet = workbook.getSheetAt(sheetIndex);
                final int rowNum = sheet.getPhysicalNumberOfRows();
                for (int rowIndex = 0; rowIndex < rowNum; rowIndex++) {
                    final Row row = sheet.getRow(rowIndex);
                    if (row == null) {
                        continue;
                    }
                    final Cell keyCell = row.getCell(0);
                    final Cell valueCell = row.getCell(1);
                    if (keyCell == null || valueCell == null) {
                        continue;
                    }

                    if (Objects.equals(keyCell.getStringCellValue(), "试题")) {
                        final String value = valueCell.getStringCellValue();
                        // 试题内容为不为空，则此题有效
                        if (isNotBlank(value)) {
                            currentIndex++;
                            currentOptionIndex = -1;
                            currentFlag = true;
                            final Question question = new Question();
                            questionList.add(question);
                            question.setQuestionContent(value);
                        } else {
                            currentFlag = false;
                        }
                    }

                    // 如果此题无效继续循环
                    if (!currentFlag) {
                        continue;
                    }

                    // 获取当前题
                    final Question question = (Question) questionList.get(currentIndex);
                    final List<SubjectOption> subjectOptions = currentOptionIndex == -1 ? new ArrayList<SubjectOption>(4) :
                            question.getOptions();
                    // 设置答案
                    if (Objects.equals(keyCell.getStringCellValue(), "答案")) {
                        final String value = valueCell.getStringCellValue().strip().toUpperCase();
                        if (OPTION_RANGE.contains(value)) {
                            question.setAnswer(value);
                        }
                    }

                    // 设置选项
                    if (Objects.equals(keyCell.getStringCellValue(), "选项")) {
                        final String value = valueCell.getStringCellValue();
                        if (value != null) {
                            currentOptionIndex++;
                            if (currentOptionIndex == OPTION_RANGE.length()) {
                                continue;
                            }
                            final SubjectOption subjectOption = new SubjectOption();
                            subjectOption.setOptionName(OPTION_RANGE.substring(currentOptionIndex, currentOptionIndex + 1));
                            subjectOption.setOptionContent(value);
                            subjectOptions.add(subjectOption);
                            question.setOptions(subjectOptions);
                        }
                    }
                }
                sheetIndex++;
            }

        }
        return;
    }
}
